#pragma once
#define RZ_INCLUDE_PTRMANAGER
#define RZ_INCLUDE_LOGGER
#define RZ_INCLUDE_RTTI
#define RZ_INCLUDE_ASSERT

#include "Config/Compiler.h"
#include "Config/OS.h"
#include "Config/BuildConfig.h"
#include "Config/Inline.h"
#include "Config/NULL.h"

#include <type_traits>	// is_base_of

#define RZ_STRINGIFY_HELPER(s)			#s
#define RZ_STRINGIFY(s)					RZ_STRINGIFY_HELPER(s)

#define RZ_COUNT_OF(s)					( sizeof(s) / (sizeof( (s)[0] )) )

#define RZ_UNUSED(p)					(p=p)

#define RZ_TYPE_FWD_DECL1(namespace1, type, name)										namespace namespace1 { type name; }
#define RZ_TYPE_FWD_DECL2(namespace1, namespace2, type, name)							namespace namespace1 { namespace namespace2 { type name; } }
#define RZ_TYPE_FWD_DECL3(namespace1, namespace2, namespace3, type, name)				namespace namespace1 { namespace namespace2 { namespace namespace3 { type name; } } }
#define RZ_TYPE_FWD_DECL4(namespace1, namespace2, namespace3, namespace4, type, name)	namespace namespace1 { namespace namespace2 { namespace namespace3 { namespace namespace4 { type name; } } } }

#define RZ_CLASS_FWD_DECL1(namespace1, name)											RZ_TYPE_FWD_DECL1(namespace1,										class, name)
#define RZ_CLASS_FWD_DECL2(namespace1, namespace2, name)								RZ_TYPE_FWD_DECL2(namespace1, namespace2,							class, name)
#define RZ_CLASS_FWD_DECL3(namespace1, namespace2, namespace3, name)					RZ_TYPE_FWD_DECL3(namespace1, namespace2, namespace3,				class, name)
#define RZ_CLASS_FWD_DECL4(namespace1, namespace2, namespace3, namespace4, name)		RZ_TYPE_FWD_DECL4(namespace1, namespace2, namespace3, namespace4,	class, name)

#define RZ_STRUCT_FWD_DECL1(namespace1, name)											RZ_TYPE_FWD_DECL1(namespace1,										struct, name)
#define RZ_STRUCT_FWD_DECL2(namespace1, namespace2, name)								RZ_TYPE_FWD_DECL2(namespace1, namespace2,							struct, name)
#define RZ_STRUCT_FWD_DECL3(namespace1, namespace2, namespace3, name) 					RZ_TYPE_FWD_DECL3(namespace1, namespace2, namespace3,				struct, name)
#define RZ_STRUCT_FWD_DECL4(namespace1, namespace2, namespace3, namespace4, name)		RZ_TYPE_FWD_DECL4(namespace1, namespace2, namespace3, namespace4,	struct, name)

#define RZ_ENUM_FWD_DECL1(namespace1, name)												RZ_TYPE_FWD_DECL1(namespace1,										enum class, name)
#define RZ_ENUM_FWD_DECL2(namespace1, namespace2, name)									RZ_TYPE_FWD_DECL2(namespace1, namespace2,							enum class, name)
#define RZ_ENUM_FWD_DECL3(namespace1, namespace2, namespace3, name) 					RZ_TYPE_FWD_DECL3(namespace1, namespace2, namespace3,				enum class, name)
#define RZ_ENUM_FWD_DECL4(namespace1, namespace2, namespace3, namespace4, name)			RZ_TYPE_FWD_DECL4(namespace1, namespace2, namespace3, namespace4,	enum class, name)

#define RZ_IS_BASE_OF(B, D)		std::is_base_of<B, D>::value
#define RZ_IMPLEMENTS(B, D)		static_assert(RZ_IS_BASE_OF(B, D), #D " do not derive from " #B "!")

// TODO
#define RZ_MARK_AS_SINGLETON(type)

